package id_util

import (
	"crypto/md5"
	"encoding/hex"
	uuid "github.com/satori/go.uuid"
	"math/rand"
	"sync"
	"time"
)

const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
const base = int64(len(chars))
const maxSuffix = int(base * base)

var simpleIdSuffix = -1
var mutex = &sync.Mutex{}
var tmp [maxSuffix]string

func init() {
	tmp[0] = "0"
	for i := 1; i < maxSuffix; i++ {
		tmp[i] = ToBigInt(int64(i))
	}
}

func UUID() string {
	return uuid.NewV1().String()
}

func MD5(str string) string {
	h := md5.New()
	h.Write([]byte(str))
	return hex.EncodeToString(h.Sum(nil))
}

func NumberID() int64 {
	return time.Now().UnixMicro()
}
func ShortID() string {
	return tmp[rand.Int()%maxSuffix] + ToBigInt(NumberID()) + idSuffix()
}

func idSuffix() string {
	mutex.Lock()
	defer mutex.Unlock()
	simpleIdSuffix += 1
	if simpleIdSuffix == maxSuffix {
		simpleIdSuffix = 0
	}
	return tmp[simpleIdSuffix]
}

func ToBigInt(num int64) string {
	bytes := make([]byte, 0, 12)
	for num > 0 {
		bytes = append(bytes, chars[num%base])
		num = num / base
	}
	// reverse(bytes)
	return string(bytes)
}

func reverse(a []byte) {
	for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
		a[left], a[right] = a[right], a[left]
	}
}
